fix(pipeline): make managed (bubbles) trigger mode actually work - #277
Merged
Conversation
Four defects, all found by running a real claude agent through a real column. Each one alone made managed mode useless for automation; together they made it look like it worked. 1. Every file edit was denied. `managed_trigger_turn_args` never passed `--dangerously-skip-permissions`, and a headless `-p` run has nobody to answer a permission prompt. The transcript is unambiguous: "Claude requested permissions to write to …/math.js, but you haven't granted it yet", repeatedly, then exit 0. An agent that changed nothing reported success. Terminal mode has always passed the flag at command-build time. The shared `ClaudeCliAdapter` deliberately does not, because chef sessions use it and are interactive — so this belongs on the trigger-only builder, where the run is unattended and sandboxed in its own worktree. 2. The pipeline never advanced. The managed path stopped at `agent_status = completed` and never called `mark_complete`, so a column with `agent_complete` + `auto_advance` worked in terminal mode and silently stalled in managed mode: finished agent, task sitting in place. It now completes behind the same moved-columns guard the terminal path uses, and only once the queued-input replay chain has ended — a pending message means the agent isn't done. 3. Uncommitted work would have been lost. Advancing into a terminal column deletes the worktree. `auto_commit_completed_worktree` existed but this path never called it, so fixing (2) would have turned a stall into data loss. It now runs before completion. Made `pub(crate)` for that. 4. An attached agent's MCP flags were dropped. `spawn_managed_trigger_task` ignored `cli_args` entirely, so an agent whose dossier advertised tools ran with none of them. Now threaded through, including into the replay turn so a queued message keeps them. Where they go matters: `--allowedTools` is declared `<tools...>` — variadic — and managed mode passes the prompt positionally, so appending the flags just before it makes claude swallow the prompt as a tool name and die with "Input must be provided either through stdin or as a prompt argument" (reproduced against 2.1.239). They are spliced in after `--print`, where a base flag closes the list. Terminal mode is unaffected; there the prompt sits behind an explicit `-p`. Also: `roster::plan` no longer emits claude's MCP flags for codex agents. `codex exec` accepts neither `--mcp-config` nor `--allowedTools` (0.145.0), so passing them would break the launch rather than merely run toolless. The gap is logged instead. Verified end to end on a real column: 0 permission denials, MCP tool called, column advanced Todo → Fix → Done, the column's model override (haiku) beat the agent's own (sonnet), and the fix landed on the branch via the rescue commit.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Four defects, all found by running a real claude agent through a real column. Each alone made managed mode useless for automation; together they made it look like it worked — the agent ran, streamed bubbles, and exited 0.
1. Every file edit was denied
managed_trigger_turn_argsnever passed--dangerously-skip-permissions, and a headless-prun has nobody to answer a permission prompt. The transcript is unambiguous:…repeatedly, then exit 0. An agent that changed nothing reported success.
Terminal mode has always passed the flag at command-build time. The shared
ClaudeCliAdapterdeliberately doesn't — chef sessions use it and are interactive — so this belongs on the trigger-only builder, where the run is unattended and sandboxed in its own worktree.2. The pipeline never advanced
The managed path stopped at
agent_status = completedand never calledmark_complete. So a column withagent_complete+auto_advanceworked in terminal mode and silently stalled in managed mode: finished agent, task sitting in place.Now completes behind the same moved-columns guard the terminal path uses, and only once the queued-input replay chain ends — a pending message means the agent isn't done.
3. Uncommitted work would have been lost
Advancing into a terminal column deletes the worktree.
auto_commit_completed_worktreeexisted but this path never called it — so fixing (2) alone would have turned a stall into data loss. It now runs before completion.Worth being precise: I initially read the missing work as a rescue bug. It wasn't — the agent had been blocked by (1) and never wrote anything, so there was nothing to rescue. The rescue only proved necessary once permissions were fixed and the agent could actually edit.
4. An attached agent's MCP flags were dropped
spawn_managed_trigger_taskignoredcli_argsentirely, so an agent whose dossier advertised tools ran with none. Now threaded through, including into the replay turn.Ordering matters:
--allowedToolsis declared<tools...>— variadic — and managed mode passes the prompt positionally. Appending the flags just before it makes claude swallow the prompt as a tool name and die withInput must be provided either through stdin or as a prompt argument(reproduced against 2.1.239). They're spliced in after--print, where a base flag closes the list. Terminal mode is unaffected — the prompt sits behind an explicit-p.Also: codex no longer gets claude's MCP flags
roster::planwas emitting--mcp-config/--allowedToolsfor codex agents too.codex execaccepts neither (0.145.0), so that would break the launch rather than merely run toolless. Withheld, and the gap is logged.Verified end to end on a real column
Isolated data dir, real repo, planted bug, a purpose-built stdio MCP server so "tools arrived" is observable rather than assumed:
return a + b, preserved via the rescue commitChecks
cargo clippy -D warnings·cargo test --lib564 (+4) ·tsc·eslint·test:ipc·test:type-scale·vitest444.(The 6
kaitencode-mcpfailures are the known local artifact of a running app intercepting the API — green on CI.)